using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SilkSharp
{
	/*
	 * Noise shaping analysis state.
	 * 
	 * @author Jing Dai
	 * @author Dingxin Xu
	 */
	public class SKP_Silk_shape_state_FLP
	{
		public int LastGainIndex;
		public float HarmBoost_smth;
		public float HarmShapeGain_smth;
		public float Tilt_smth;

		/*
		 * set all fields of the instance to zero
		 */
		public void memZero()
		{
			this.LastGainIndex = 0;
			this.HarmBoost_smth = 0;
			this.HarmShapeGain_smth = 0;
			this.Tilt_smth = 0;
		}
	}

	/*
	 * Prefilter state 
	 * 
	 * @author Jing Dai
	 * @author Dingxin Xu
	 */
	public class SKP_Silk_prefilter_state_FLP
	{
		public float[] sLTP_shp1 = new float[ Silk_define.LTP_BUF_LENGTH ];
		public float[] sLTP_shp2 = new float[ Silk_define.LTP_BUF_LENGTH ];
		public float[] sAR_shp1 = new float[ Silk_define.SHAPE_LPC_ORDER_MAX + 1 ];
		public float[] sAR_shp2 = new float[ Silk_define.SHAPE_LPC_ORDER_MAX ];
		public int sLTP_shp_buf_idx1;
		public int sLTP_shp_buf_idx2;
		public int sAR_shp_buf_idx2;
		public float sLF_AR_shp1;
		public float sLF_MA_shp1;
		public float sLF_AR_shp2;
		public float sLF_MA_shp2;
		public float sHarmHP;
		public int rand_seed;
		public int lagPrev;

		/*
		 * set all fields of the instance to zero
		 */
		public void memZero()
		{
			Silk_macros.FillArray<float>( this.sAR_shp1, 0 );
			Silk_macros.FillArray<float>( this.sAR_shp2, 0 );
			Silk_macros.FillArray<float>( this.sLTP_shp1, 0 );
			Silk_macros.FillArray<float>( this.sLTP_shp2, 0 );

			this.sLTP_shp_buf_idx1 = 0;
			this.sLTP_shp_buf_idx2 = 0;
			this.sAR_shp_buf_idx2 = 0;
			this.sLF_AR_shp1 = 0;
			this.sLF_AR_shp2 = 0;
			this.sLF_MA_shp1 = 0;
			this.sLF_MA_shp2 = 0;
			this.sHarmHP = 0;
			this.rand_seed = 0;
			this.lagPrev = 0;
		}
	}

	/*
	 * Prediction analysis state
	 * 
	 * @author Jing Dai
	 * @author Dingxin Xu
	 */
	public class SKP_Silk_predict_state_FLP
	{
		public int pitch_LPC_win_length;
		public int min_pitch_lag;                      /* Lowest possible pitch lag (samples)  */
		public int max_pitch_lag;                      /* Highest possible pitch lag (samples) */
		public float[] prev_NLSFq = new float[ Silk_define.MAX_LPC_ORDER ];        /* Previously quantized NLSF vector     */

		/*
		 * set all fields of the instance to zero
		 */
		public void memZero()
		{
			this.pitch_LPC_win_length = 0;
			this.max_pitch_lag = 0;
			this.min_pitch_lag = 0;
			Silk_macros.FillArray<float>( this.prev_NLSFq, 0.0f );
		}
	}

	/*******************************************/
	/* Structure containing NLSF MSVQ codebook */
	/*******************************************/
	/* structure for one stage of MSVQ */
	public class SKP_Silk_NLSF_CBS_FLP
	{
		public SKP_Silk_NLSF_CBS_FLP( int nVectors, float[] CB, float[] Rates )
		{
			this.nVectors = nVectors;
			this.CB = CB;
			this.Rates = Rates;
		}

		public SKP_Silk_NLSF_CBS_FLP( int nVectors, float[] CB, int CB_offset, float[] Rates, int Rates_offset )
		{
			this.nVectors = nVectors;
			this.CB = new float[ CB.Length - CB_offset ];
			System.Array.Copy( CB, CB_offset, this.CB, 0, this.CB.Length );
			this.Rates = new float[ Rates.Length - Rates_offset ];
			System.Array.Copy( Rates, Rates_offset, this.Rates, 0, this.Rates.Length );
		}

		public int nVectors;
		public float[] CB;
		public float[] Rates;
	}

	public class SKP_Silk_NLSF_CB_FLP
	{
		public SKP_Silk_NLSF_CB_FLP( int nStages, SKP_Silk_NLSF_CBS_FLP[] CBStages,
				float[] NDeltaMin, int[] CDF, int[][] StartPtr, int[] MiddleIx )
		{
			this.nStages = nStages;
			this.CBStages = CBStages;
			this.NDeltaMin = NDeltaMin;
			this.CDF = CDF;
			this.StartPtr = StartPtr;
			this.MiddleIx = MiddleIx;
		}
		//const SKP_int32                         nStages;    
		public int nStages;

		/* fields for (de)quantizing */
		public SKP_Silk_NLSF_CBS_FLP[] CBStages;
		float[] NDeltaMin;

		/* fields for arithmetic (de)coding */
		//    const SKP_uint16                        *CDF;
		int[] CDF;
		//    const SKP_uint16 * const                *StartPtr;
		int[][] StartPtr;
		//    const SKP_int                           *MiddleIx;
		int[] MiddleIx;
	}

	/************************************/
	/* Noise shaping quantization state */
	/************************************/

	/*
	 * Encoder state FLP.
	 * 
	 * @author Jing Dai
	 * @author Dingxin Xu
	 */
	public class SKP_Silk_encoder_state_FLP
	{
		//    SKP_Silk_encoder_state              sCmn;                       /* Common struct, shared with fixed-point code */
		public SKP_Silk_encoder_state sCmn = new SKP_Silk_encoder_state(); /* Common struct, shared with fixed-point code */


		public float variable_HP_smth1;          /* State of first smoother */
		public float variable_HP_smth2;          /* State of second smoother */

		public SKP_Silk_shape_state_FLP sShape = new SKP_Silk_shape_state_FLP();                     /* Noise shaping state */
		public SKP_Silk_prefilter_state_FLP sPrefilt = new SKP_Silk_prefilter_state_FLP();                   /* Prefilter State */
		public SKP_Silk_predict_state_FLP sPred = new SKP_Silk_predict_state_FLP();                      /* Prediction State */
		public SKP_Silk_nsq_state sNSQ = new SKP_Silk_nsq_state();                       /* Noise Shape Quantizer State */
		public SKP_Silk_nsq_state sNSQ_LBRR = new SKP_Silk_nsq_state();                  /* Noise Shape Quantizer State ( for low bitrate redundancy )*/

		/* Function pointer to noise shaping quantizer (will be set to SKP_Silk_NSQ or SKP_Silk_NSQ_del_dec) */
		//    void    (* NoiseShapingQuantizer)( SKP_Silk_encoder_state *, SKP_Silk_encoder_control *, SKP_Silk_nsq_state *, const SKP_int16 *, 
		//                                       SKP_int8 *, const SKP_int, const SKP_int16 *, const SKP_int16 *, const SKP_int16 *, const SKP_int *, 
		//                                        const SKP_int *, const SKP_int32 *, const SKP_int32 *, SKP_int, const SKP_int
		//    );
		public NoiseShapingQuantizerFP noiseShapingQuantizerCB;
		public void NoiseShapingQuantizer( SKP_Silk_encoder_state psEnc, SKP_Silk_encoder_control psEncCtrl, SKP_Silk_nsq_state NSQ, short[] x,
			byte[] q, int arg6, short[] arg7, short[] arg8, short[] arg9, int[] arg10,
			 int[] arg11, int[] arg12, int[] arg13, int arg14, int arg15
		)
		{
			noiseShapingQuantizerCB.NoiseShapingQuantizer( psEnc, psEncCtrl, NSQ, x, q, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15 );
		}


		/* Buffer for find pitch and noise shape analysis */
		public float[] x_buf = new float[ 2 * Silk_define.MAX_FRAME_LENGTH + Silk_define.LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
		// djinn: add a parameter: offset
		public int x_buf_offset;
		public float LTPCorr;                    /* Normalized correlation from pitch lag estimator */
		public float mu_LTP;                     /* Rate-distortion tradeoff in LTP quantization */
		public float SNR_dB;                     /* Quality setting */
		public float avgGain;                    /* average gain during active speech */
		public float BufferedInChannel_ms;       /* Simulated number of ms buffer in channel because of exceeded TargetRate_bps */
		public float speech_activity;            /* Speech activity */
		public float pitchEstimationThreshold;   /* Threshold for pitch estimator */

		/* Parameters for LTP scaling control */
		public float prevLTPredCodGain;
		public float HPLTPredCodGain;

		public float inBandFEC_SNR_comp;         /* Compensation to SNR_DB when using inband FEC Voiced */

		public SKP_Silk_NLSF_CB_FLP[] psNLSF_CB_FLP = new SKP_Silk_NLSF_CB_FLP[ 2 ];        /* Pointers to voiced/unvoiced NLSF codebooks */
	}

	/*
	 * Encoder control FLP
	 * 
	 * @author Jing Dai
	 * @author Dingxin Xu
	 */
	public class SKP_Silk_encoder_control_FLP
	{
		public SKP_Silk_encoder_control sCmn = new SKP_Silk_encoder_control();                               /* Common struct, shared with fixed-point code */

		/* Prediction and coding parameters */
		public float[] Gains = new float[ Silk_define.NB_SUBFR ];
		public float[][] PredCoef = Silk_macros.MakeJaggedArray<float>( 2, Silk_define.MAX_LPC_ORDER );     /* holds interpolated and final coefficients */
		public float[] LTPCoef = new float[ Silk_define.LTP_ORDER * Silk_define.NB_SUBFR ];
		public float LTP_scale;

		/* Prediction and coding parameters */
		public int[] Gains_Q16 = new int[ Silk_define.NB_SUBFR ];
		//TODO:    SKP_array_of_int16_4_byte_aligned( PredCoef_Q12[ 2 ], MAX_LPC_ORDER );
		public int[] dummy_int32PredCoef_Q12 = new int[ 2 ];
		public short[ , ] PredCoef_Q12 = new short[ 2, Silk_define.MAX_LPC_ORDER ];

		public short[] LTPCoef_Q14 = new short[ Silk_define.LTP_ORDER * Silk_define.NB_SUBFR ];
		public int LTP_scale_Q14;

		/* Noise shaping parameters */
		/* Testing */
		//TODO    SKP_array_of_int16_4_byte_aligned( AR2_Q13, NB_SUBFR * SHAPE_LPC_ORDER_MAX );
		public int dummy_int32AR2_Q13;
		public short[] AR2_Q13 = new short[ Silk_define.NB_SUBFR * Silk_define.SHAPE_LPC_ORDER_MAX ];

		public int[] LF_shp_Q14 = new int[ Silk_define.NB_SUBFR ];      /* Packs two int16 coefficients per int32 value             */
		public int[] Tilt_Q14 = new int[ Silk_define.NB_SUBFR ];
		public int[] HarmShapeGain_Q14 = new int[ Silk_define.NB_SUBFR ];
		public int Lambda_Q10;

		/* Noise shaping parameters */
		public float[] AR1 = new float[ Silk_define.NB_SUBFR * Silk_define.SHAPE_LPC_ORDER_MAX ];
		public float[] AR2 = new float[ Silk_define.NB_SUBFR * Silk_define.SHAPE_LPC_ORDER_MAX ];
		public float[] LF_MA_shp = new float[ Silk_define.NB_SUBFR ];
		public float[] LF_AR_shp = new float[ Silk_define.NB_SUBFR ];
		public float[] GainsPre = new float[ Silk_define.NB_SUBFR ];
		public float[] HarmBoost = new float[ Silk_define.NB_SUBFR ];
		public float[] Tilt = new float[ Silk_define.NB_SUBFR ];
		public float[] HarmShapeGain = new float[ Silk_define.NB_SUBFR ];
		public float Lambda; //Achievement Unlocked: Lambda Locator
		public float input_quality;
		public float coding_quality;
		public float pitch_freq_low_Hz;
		public float current_SNR_dB;

		/* Measures */
		public float sparseness;
		public float LTPredCodGain;
		public float[] input_quality_bands = new float[ Silk_define.VAD_N_BANDS ];
		public float input_tilt;
		public float[] ResNrg = new float[ Silk_define.NB_SUBFR ];                 /* Residual energy per subframe */
	}

	public interface NoiseShapingQuantizerFP
	{
		/* Function pointer to noise shaping quantizer (will be set to SKP_Silk_NSQ or SKP_Silk_NSQ_del_dec) */
		void NoiseShapingQuantizer( SKP_Silk_encoder_state psEnc, SKP_Silk_encoder_control psEncCtrl, SKP_Silk_nsq_state NSQ, short[] x,
										   byte[] q, int arg6, short[] arg7, short[] arg8, short[] arg9, int[] arg10,
											int[] arg11, int[] arg12, int[] arg13, int arg14, int arg15
		);
	}
}
